﻿using Framework.LogServices.Models;
using Microsoft.Data.SqlClient;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Text.Json;
using Newtonsoft.Json;

namespace Framework.LogServices
{
    /// <summary>
    /// 记录sqlserver的日志队列
    /// </summary>
    public static class UnlimitedLocalLogging
    {
        /// <summary>
        /// 数据库链接字符串
        /// </summary>
        private readonly static string connection = "";
        /// <summary>
        /// 数据结构
        /// </summary>
        private readonly static DataTable dt_column;

        /// <summary>
        /// 先进先出日志消息队列
        /// </summary>
        private static ConcurrentQueue<LogEntry> _logQueue = new ConcurrentQueue<LogEntry>();

        /// <summary>
        /// 用于通知后台任务停止的信号
        /// </summary>
        private static readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();

        /// <summary>
        /// 后台处理任务
        /// </summary>
        private static readonly Task _backgroundTask;

        /// <summary>
        /// 不重复的电站ID字典
        /// </summary>
        private static readonly ConcurrentDictionary<string, byte> pwIdInfo = new ConcurrentDictionary<string, byte>();


        static UnlimitedLocalLogging()
        {
            dt_column = new DataTable();
            dt_column.Columns.Add("id", typeof(Guid));
            dt_column.Columns.Add("key");
            dt_column.Columns.Add("value");
            dt_column.Columns.Add("type");
            dt_column.Columns.Add("createtime");

            if (connection == null)
            {
                //using (Entities db = new Entities())
                //{
                //    connection = db.Database.Connection.ConnectionString;
                //}
            }

            //启动后台任务
            _backgroundTask = Task.Factory.StartNew(() => ProcessLogQueue(_cancellationTokenSource.Token).ConfigureAwait(false), TaskCreationOptions.LongRunning);
        }

        static ConcurrentDictionary<string, int> keyValuePairs = new ConcurrentDictionary<string, int>();

        /// <summary>
        /// 后台任务
        /// </summary>
        private static async Task ProcessLogQueue(CancellationToken cancellationToken)
        {
            // 批量处理的大小
            const int batchSize = 1000;
            // 当队列为空时的等待延迟（毫秒）
            const int emptyQueueDelay = 100;

            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    List<LogEntry> logBatch = new List<LogEntry>(batchSize);
                    // 从队列中取出最多 batchSize 条日志
                    while (_logQueue.TryDequeue(out LogEntry logEntry))
                    {
                        if (logEntry.Level.ToLower().Trim() == "pwid")
                        {
                            if (pwIdInfo.ContainsKey(logEntry.Message))
                            {
                                continue;
                            }
                            else
                            {
                                pwIdInfo.TryAdd(logEntry.Message, 0);
                            }
                        }
                        logBatch.Add(logEntry);
                        if (logBatch.Count >= batchSize) break;
                    }

                    if (logBatch.Count > 0)
                    {
                        // 如果有日志，则批量插入
                        await BulkInsertLogsAsync(logBatch);
                    }
                    else
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            Console.WriteLine($"{DateTime.Now} --> 后台日志任务已标记取消");
                            return;
                        }
                        // 如果队列为空，等待一段时间再检查，避免CPU空转
                        await Task.Delay(emptyQueueDelay, cancellationToken);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"{DateTime.Now} --> 日志记录时出现未知异常: {ex.Message}，异常明细：{ex}");
                    LocalLoggingFile.ErrorLog($"后台任务日志记录时出现未知异常", ex);
                    // 短暂等待后继续，避免错误循环疯狂刷日志
                    await Task.Delay(1000, cancellationToken);
                }
            }
        }

        /// <summary>
        /// 写入数据库
        /// </summary>
        /// <param name="logEntries"></param>
        /// <returns></returns>
        private static async Task BulkInsertLogsAsync(List<LogEntry> logEntries)
        {
            if (logEntries.Count <= 0) return;
            DataTable dt = dt_column.Clone();
            logEntries.ForEach(logEntry =>
            {
                if (keyValuePairs.ContainsKey(logEntry.Level))
                {
                    keyValuePairs[logEntry.Level] += 1;
                }
                else
                {
                    keyValuePairs.TryAdd(logEntry.Level, 1);
                }
                DataRow dr = dt.NewRow();
                dr["id"] = Guid.NewGuid();
                dr["key"] = logEntry.Level.ToLower().Trim() == "pwid" ? logEntry.Message : logEntry.key ?? logEntry.Level;
                dr["value"] = logEntry.Message;
                dr["type"] = logEntry.Level;
                dr["createtime"] = logEntry.Timestamp;
                if (logEntry.Exception != null)
                {
                    dr["value"] = $"{logEntry.Message} --> 异常信息: {logEntry.Exception}";
                }

                dt.Rows.Add(dr);
            });
            try
            {
                using (SqlConnection conn = new SqlConnection(connection))
                {
                    conn.Open();
                    using (SqlBulkCopy sbc = new SqlBulkCopy(conn))
                    {
                        sbc.DestinationTableName = "gops_semsplus_mongoinit_log_temp";

                        sbc.BatchSize = 5000; // 每批处理的行数
                        sbc.BulkCopyTimeout = 600; // 超时时间（秒）
                        sbc.NotifyAfter = 1000; // 每处理多少行后触发通知事件
                        sbc.EnableStreaming = true;

                        //将Datatable批量写入数据库
                        await sbc.WriteToServerAsync(dt);
                    }
                }
            }
            catch (TimeoutException)
            {

            }
            catch (Exception ex)
            {
                Console.WriteLine($"{DateTime.Now}-->日志写入数据库时出现未知异常，异常信息：{ex}，异常明细：{ex}");
            }
        }

        /// <summary>
        /// 添加日志到无限队列
        /// </summary>
        private static void AddLogToQueue(string message, string level, Exception e = null)
        {
            var logEntry = new LogEntry
            {
                Message = message,
                Level = level?.ToLower() ?? "info",
                Exception = e
            };

            _logQueue.Enqueue(logEntry);

        }

        /// <summary>
        /// 记录正常日志
        /// </summary>
        public static void Log(string message)
        {
            AddLogToQueue(message, "info");
        }

        /// <summary>
        /// 记录指定级别的日志
        /// </summary>
        public static void Log(string message, string level, Exception e = null)
        {
            AddLogToQueue(message, level, e);
        }

        /// <summary>
        /// 记录异常日志
        /// </summary>
        public static void ErrorLog(string message, Exception e = null)
        {
            AddLogToQueue(message, "error", e);
        }

        /// <summary>
        /// 记录PWID日志
        /// </summary>
        public static void LogPwId(string message)
        {
            AddLogToQueue(message, "pwid");
        }
        /// <summary>
        /// 关闭日志系统
        /// </summary>
        public static void Shutdown(TimeSpan timeout)
        {
            // 1. 请求取消后台任务
            _cancellationTokenSource.Cancel();
            try
            {
                // 2. 等待后台任务完成（最多等待一定时间）
                if (!_backgroundTask.Wait(timeout))
                {
                    Console.WriteLine($"Warning: 日志记录任务未在超时内正常关闭。剩余日志数量：{_logQueue.Count}");
                }
            }
            catch (AggregateException ex)
            {
                // 处理等待任务时可能出现的异常
                Console.WriteLine($"关闭日志时出现未知异常: {ex.InnerException?.Message}，异常信息：{ex}");
                LocalLoggingFile.ErrorLog($"关闭日志时出现未知异常", ex);
            }
            finally
            {
                _cancellationTokenSource.Dispose();
                Console.WriteLine($"{DateTime.Now} --> 日志系统已关闭。队列中剩余 {_logQueue.Count} 条日志未处理。已处理日志总量：{keyValuePairs.Select(x => x.Value).Sum()}，处理明细：{JsonConvert.SerializeObject(keyValuePairs)}");
            }
        }
    }
}
